﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Utilities;
using System.Collections;
using System.Text.RegularExpressions;
using StockCommon.baseclass;

namespace StockCommon.Calendar
{
    public class CalenderHelper:DBAccess
    {
        private Hashtable _NoTradeDateHash = new Hashtable();
        List<NoTradeDate> noTradeDates = new List<NoTradeDate>();

        protected static int dataValidHour = 16;

        /*************************************************************************************
         *  取得有交易資料的日期,如果是如果是9點以前,則必須要是前一天
         * 
         *************************************************************************************/
        public static DateTime getLastTradeDataDate()
        {
            DateTime dt = new DateTime();
            Boolean offseted = false;
            if (dt.DayOfWeek.Equals(DayOfWeek.Monday))
            {
                if (dt.Hour >= dataValidHour)//九點以後
                {
                    return new DateTime(dt.Year, dt.Month, dt.Day);
                }
                dt.AddDays(-1);
                offseted = true;
            }
            while ((dt.DayOfWeek.Equals(DayOfWeek.Sunday) || dt.DayOfWeek.Equals(DayOfWeek.Sunday)))
            {
                dt = dt.AddDays(-1);
                offseted = true;
            }
            if (offseted)
            {
                return new DateTime(dt.Year, dt.Month, dt.Day);
            }
            else
            {
                if (dt.Hour >= dataValidHour)
                    return new DateTime(dt.Year, dt.Month, dt.Day);
                else
                {
                    dt = dt.AddDays(-1);
                    return new DateTime(dt.Year, dt.Month, dt.Day);
                }
            }
        }
        public static void addNoTrade(DateTime date, String Event)
        {
            StockDataClassesDataContext context = getContext();
            NoTradeDate ndd = (from nd in context.NoTradeDates where nd.日期 == date select nd).FirstOrDefault<NoTradeDate>();
            if (ndd == null)
            {
                ndd = new NoTradeDate();
                ndd.日期 = date;
                ndd.市場 = "台灣";
                ndd.事件 = Event;
                context.NoTradeDates.InsertOnSubmit(ndd);
                context.SubmitChanges();
            }
            setNoTrade(date);
        }
        public List<NoTradeDate> NoTradeDates
        {
            get { return noTradeDates; }
            set { noTradeDates = value; }
        }
        public void LoadNoTradeDate()
        {
            StockDataClassesDataContext context = getContext();
            List<NoTradeDate> ll = (from d in context.NoTradeDates orderby d.日期 select d).ToList<NoTradeDate>();
            noTradeDates = ll;

            foreach (NoTradeDate d in ll)
            {
                _NoTradeDateHash.Add(d.日期, d.事件);
            }
        }

        public static void makeCalendar(DateTime start, DateTime end)
        {
            if (end.CompareTo(start) < 0)
            {
                DateTime tmp = start;
                start = end;
                end = tmp;
            }
            String ss = DateUtils.toYYYYMMDD_Slash(start);
            start = DateTime.Parse(ss);
            String se = DateUtils.toYYYYMMDD_Slash(end);
            end = DateTime.Parse(se);

            StockDataClassesDataContext context = getContext();
            String sql = String.Format("delete from TradeCalendar where date >= '{0}' and date <= '{1}'", ss, se);
            context.ExecuteCommand(sql);

            DateTime curDate = start;
            while (curDate.CompareTo(end) <= 0)
            {
                TradeCalendar rec = new TradeCalendar();
                rec.date = curDate;
                rec.Year = curDate.Year;
                int d = curDate.Day;
                int w = DateUtils.GetWeekNumber(curDate);
                rec.week = w;
                int m = curDate.Month;
                rec.Month = m;
                if ((w > 50) && (m == 1))
                    rec.YearByWeek = rec.Year - 1;
                else
                    rec.YearByWeek = rec.Year;
                rec.YearWeekKey = rec.YearByWeek * 100 + rec.week;

                if (curDate.DayOfWeek.Equals(DayOfWeek.Saturday) || curDate.DayOfWeek.Equals(DayOfWeek.Sunday))
                {
                    rec.hasTrade = false;
                }
                else
                    rec.hasTrade = true;
                context.TradeCalendars.InsertOnSubmit(rec);
                curDate = curDate.AddDays(1.0);
            }
            context.SubmitChanges();
        }

        public static void parseNotWorkDay(String[]   lines)
        {
            Regex dateRegx = new Regex(@"(\d+)/(\d+)/(\d+)", RegexOptions.IgnoreCase);

            foreach (String s in lines)
            {
                String s1 = s.Trim();
                Match m = dateRegx.Match(s1);
                if (m.Success)
                {
                    String seg=m.Groups[0].ToString();
                    String s2 = s1.Substring(seg.Length);
                    s2 = s2.Trim();
                    DateTime d=DateTime.Parse(seg);
                    CalenderHelper.addNoTrade(d,s2);
                    //UpdateScheduleNaviServices.logItem(d, "休市", s2, 10);
                }
            }
            DateTime dd = DateTime.Parse("2012/01/01");
            DateTime dc = DateTime.Parse("2003/12/31");
            while (true)
            {
                if (dd.CompareTo(dc) < 0)
                    break;
                CalenderHelper.addNoTrade(dd, "元旦");
                //UpdateScheduleNaviServices.logItem(dd, "休市", "元旦", 10);
                dd=dd.AddYears(-1);
            }

        }
        public static DateTime getCalendarStart()
        {
            String sql = "select MIN(date) from TradeCalendar";
            var d = getContext().ExecuteQuery<DateTime?>(sql).FirstOrDefault();
            return (d != null) ? (DateTime)d : DateTime.Now;
        }
        public static DateTime getCalendarEnd()
        {
            String sql = "select MAX(date) from TradeCalendar";
            var d = getContext().ExecuteQuery<DateTime?>(sql).FirstOrDefault();
            return (d != null) ? (DateTime)d : DateTime.Now;
                
        }
        public static void setFixVacation(DateTime dt,String eventDesc)
        {
            DateTime maxd = getCalendarEnd();
            DateTime mind = getCalendarStart();

            DateTime d1 = new DateTime(maxd.Year, dt.Month, dt.Day);
            if (d1.CompareTo(maxd) > 0)
                d1=d1.AddYears(-1);
            while (true)
            {
                if (d1.CompareTo(mind) < 0)
                    break;
                CalenderHelper.addNoTrade(d1, eventDesc);
                d1 = d1.AddYears(-1);
            }
            
        }
        
        public static bool isWorkDay(DateTime date)
        {
            if (date.DayOfWeek.Equals(DayOfWeek.Sunday) ||
                   date.DayOfWeek.Equals(DayOfWeek.Saturday))
            {
                return false;
            }
             StockDataClassesDataContext context=getContext();
             var r = (from t in context.TradeCalendars where t.date == date select new { t.date, t.hasTrade }).FirstOrDefault();
             if (r != null)
                 return (bool)r.hasTrade;
             return true;
            //TODO 2.考慮加上cache
        }
        protected static void setNoTrade(DateTime dt)
        {
            String sql=string.Format("update TradeCalendar set hasTrade=0 where date='{0}'",DateUtils.toYYYYMMDD_Slash(dt));
            getContext().ExecuteCommand(sql);
        }
    }
}
